package com.gpframework.module.process.service.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.gpframework.common.core.domain.AjaxResult;
import com.gpframework.common.enums.YesNoEnum;
import com.gpframework.common.exception.BaseException;
import com.gpframework.common.utils.DateUtils;
import com.gpframework.common.utils.StringUtils;
import com.gpframework.module.manufacture.domain.GpProduceProduct;
import com.gpframework.module.manufacture.domain.GpProductionScheduling;
import com.gpframework.module.manufacture.service.IGpProduceProductService;
import com.gpframework.module.process.domain.GpProcessDeliveryNote;
import com.gpframework.module.process.domain.GpProcessManagement;
import com.gpframework.module.process.domain.req.GpProcessSchedulingUpdate;
import com.gpframework.module.process.service.IGpProcessDeliveryNoteService;
import com.gpframework.module.process.service.IGpProcessManagementService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gpframework.module.process.mapper.GpProcessSchedulingMapper;
import com.gpframework.module.process.domain.GpProcessScheduling;
import com.gpframework.module.process.domain.vo.GpProcessSchedulingVo;
import com.gpframework.module.process.service.IGpProcessSchedulingService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @ClassName GpProcessScheduling
 * @Author gpframework
 * @Date 2023-12-20
 * @Version 1.0.0
 * @Description 排单Service业务层处理
 */
@Service
public class GpProcessSchedulingServiceImpl extends ServiceImpl<GpProcessSchedulingMapper, GpProcessScheduling> implements IGpProcessSchedulingService {

    @Autowired
    private  IGpProduceProductService iGpProduceProductService;

    @Autowired
    private IGpProcessManagementService iGpProcessManagementService;

    @Autowired
    private  IGpProcessDeliveryNoteService iGpProcessDeliveryNoteService;

    /**
     * @Description 查询列表返回VO 用于返回给前端的列表接口
     * @Author gpframework
     * @Date 2023-12-20
     * @Param [lqw]
     * @Return List<GpProcessSchedulingVo>
     */
    @Override
    public List<GpProcessSchedulingVo> listVo(QueryWrapper<GpProcessScheduling> lqw) {
        return this.baseMapper.listVo(lqw);
    }

    /**
     * @Description 通过查询详情VO 用于返回给前端的列详情接口
     * @Author gpframework
     * @Date 2023-12-20
     * @Param [id]
     * @Return GpProcessSchedulingVo
     */
    @Override
    public GpProcessSchedulingVo getVoById(Long id) {
        return this.baseMapper.getVo(id);
    }

    @Override
    public void savebase(GpProcessScheduling gpProcessScheduling) {
        // 从产品基础表获取品名、颜色
        if (StringUtils.isNotBlank(gpProcessScheduling.getProductName()) && StringUtils.isNotBlank(gpProcessScheduling.getProductColor())) {
            GpProduceProduct gpProduceProduct = iGpProduceProductService.getOne(new LambdaQueryWrapper<GpProduceProduct>()
                    .eq(GpProduceProduct::getProductName, gpProcessScheduling.getProductName())
                    .eq(GpProduceProduct::getColour, gpProcessScheduling.getProductColor())
                    .eq(GpProduceProduct::getDelStatus, YesNoEnum.NO.getKey())
                    .last("limit 1"));
            if (gpProduceProduct == null) {
                gpProduceProduct = new GpProduceProduct();
                gpProduceProduct.setProductName(gpProcessScheduling.getProductName());
                gpProduceProduct.setColour(gpProcessScheduling.getBackerColor());
                iGpProduceProductService.save(gpProduceProduct);
            }
            gpProcessScheduling.setProductName(gpProduceProduct.getProductName());
            gpProcessScheduling.setProductColor(gpProduceProduct.getColour());
        }

        // 从加工商管理基础表获取花型、加工商
        if (StringUtils.isNotBlank(gpProcessScheduling.getFlowerPattern()) && StringUtils.isNotBlank(gpProcessScheduling.getProcessor())) {
            GpProcessManagement gpProcessManagement = iGpProcessManagementService.getOne(new LambdaQueryWrapper<GpProcessManagement>()
                    .eq(GpProcessManagement::getProcessor, gpProcessScheduling.getProcessor())
                    .eq(GpProcessManagement::getFlowerPattern, gpProcessScheduling.getFlowerPattern())
                    .eq(GpProcessManagement::getDelStatus, YesNoEnum.NO.getKey())
                    .last("limit 1"));
            if (gpProcessManagement == null) {
                gpProcessManagement = new GpProcessManagement();
                gpProcessManagement.setProcessor(gpProcessScheduling.getProcessor());
                gpProcessManagement.setFlowerPattern(gpProcessScheduling.getFlowerPattern());
                iGpProcessManagementService.save(gpProcessManagement);
            }
            gpProcessManagement.setProcessor(gpProcessScheduling.getProcessor());
            gpProcessManagement.setFlowerPattern(gpProcessScheduling.getFlowerPattern());
        }

    }

    @Override
    public boolean edit(List<GpProcessSchedulingUpdate> gpProcessSchedulingUpdates) {
        ArrayList<GpProcessScheduling> gpProcessSchedulingList = new ArrayList<>();
        for (GpProcessSchedulingUpdate gpProcessSchedulingUpdate : gpProcessSchedulingUpdates) {
            GpProcessScheduling gpProcessScheduling = Convert.convert(new TypeReference<GpProcessScheduling>() {}, gpProcessSchedulingUpdate);
            //保存基础表信息
            this.savebase(gpProcessScheduling);
            gpProcessSchedulingList.add(gpProcessScheduling);
        }

        return this.updateBatchById(gpProcessSchedulingList);
    }


    @Override
    public boolean createReceiveGoods(List<Long> ids, String createBy) {
        ArrayList<GpProcessDeliveryNote> gpProcessDeliveryNotes = new ArrayList<>();
        for (Long id : ids) {
            GpProcessScheduling gpProcessScheduling = this.getById(id);
            GpProcessDeliveryNote gpProcessDeliveryNote = new GpProcessDeliveryNote();
            GpProcessManagement gpProcessManagement = iGpProcessManagementService.getOne(new QueryWrapper<GpProcessManagement>().eq("processor",gpProcessScheduling.getProcessor()).eq("del_status",YesNoEnum.NO.getKey()).last("limit 1"));
            if (gpProcessManagement != null && gpProcessManagement.getProcessorCode() != null) {
                gpProcessDeliveryNote.setDyeVatNo(gpProcessManagement.getProcessorCode() + DateUtils.getDate(DateUtils.YYMMDD));
            } else {
                gpProcessDeliveryNote.setDyeVatNo(DateUtils.getDate(DateUtils.YYMMDD));
            }
            if (StringUtils.isNotBlank(createBy)) {
                gpProcessDeliveryNote.setCreateBy(createBy);
            }
            gpProcessDeliveryNote.setSn(gpProcessScheduling.getSn());

            gpProcessDeliveryNote.setSendOutGoodsTime(new Date());

            gpProcessDeliveryNote.setProductionApplicationId(gpProcessScheduling.getProductionApplicationId());
            gpProcessDeliveryNote.setProcessSchedulingId(gpProcessScheduling.getId());
            gpProcessDeliveryNote.setProcessor(gpProcessScheduling.getProcessor());
            gpProcessDeliveryNote.setProductName(gpProcessScheduling.getProductName());
            gpProcessDeliveryNote.setProductColor(gpProcessScheduling.getProductColor());
            gpProcessDeliveryNote.setDocumentaryId(gpProcessScheduling.getDocumentaryId());
            gpProcessDeliveryNote.setDocumentaryMan(gpProcessScheduling.getDocumentaryMan());

            gpProcessDeliveryNotes.add(gpProcessDeliveryNote);
        }

        return  iGpProcessDeliveryNoteService.saveBatch(gpProcessDeliveryNotes);
    }

    @Override
    @Transactional
    public boolean confirmOrder(List<GpProcessSchedulingUpdate> gpProcessSchedulingUpdates) {
        this.edit(gpProcessSchedulingUpdates);
        List<Long> ids = gpProcessSchedulingUpdates.stream().map(GpProcessSchedulingUpdate::getId).collect(Collectors.toList());
        this.createReceiveGoods(ids, null);
        return true;
    }

    @Override
    public boolean editOne(GpProcessSchedulingUpdate gpProcessSchedulingUpdate) {
        GpProcessScheduling gpProcessScheduling = Convert.convert(new TypeReference<GpProcessScheduling>() {}, gpProcessSchedulingUpdate);
        //保存基础表信息
        this.savebase(gpProcessScheduling);
        return this.updateById(gpProcessScheduling);
    }


    @Override
    public boolean applyReturnBottomCloth(GpProcessSchedulingUpdate gpProcessSchedulingUpdate) {
        for (Long id : gpProcessSchedulingUpdate.getIds()) {
            GpProcessScheduling scheduling = this.getById(id);
            if (scheduling == null) {
                throw new BaseException("请选择一行数据");
            }
            int count = iGpProcessDeliveryNoteService.count(new QueryWrapper<GpProcessDeliveryNote>().eq("process_scheduling_id", id));
            if (count== 0) {
                throw new BaseException("请先生成到货单");
            }
        }
        //设置到货单
        iGpProcessDeliveryNoteService.update(new UpdateWrapper<GpProcessDeliveryNote>()
                .set("done_quantity", gpProcessSchedulingUpdate.getDoneQuantity())
                .set("undone_quantity", gpProcessSchedulingUpdate.getUndoneQuantity())
                .in("process_scheduling_id", gpProcessSchedulingUpdate.getIds()
                ));
        return true;
    }

    @Override
    public boolean splitOrders(Long id, Long splitNum) {
        GpProcessScheduling gpProcessScheduling = this.getById(id);
        if (gpProcessScheduling == null) {
            return false;
        }

        if (gpProcessScheduling.getNum()==0){
            throw new BaseException("拆分的数量(码)不能为空");
        }
        //改变原有订单
        if (gpProcessScheduling.getNum()-splitNum<0){
            throw new BaseException("拆分的数量(码):"+splitNum+"大于原订单数:"+gpProcessScheduling.getNum());
        }
        gpProcessScheduling.setNum(gpProcessScheduling.getNum()-splitNum);
        this.updateById(gpProcessScheduling);

        String sn = gpProcessScheduling.getSn();
        String newSn = "";
        String[] split = sn.split("-");
        if (split.length < 3){
             newSn = split[0] + "-" + split[1] + "-" + 1;
        } else {
            newSn = split[0] + "-" + split[1] + "-" +  (Integer.parseInt(split[2]) + 1);
        }
        //新增拆分订单
        gpProcessScheduling.setId(null);
        gpProcessScheduling.setNum(splitNum);
        gpProcessScheduling.setSn(newSn);
        this.save(gpProcessScheduling);
        return true;
    }

    @Override
    public boolean copy(Long id, Integer copyNum) {
        GpProcessScheduling gpProcessScheduling = this.getById(id);
        if (gpProcessScheduling == null) {
            return false;
        }
        for (int i = 0; i < copyNum; i++) {
            gpProcessScheduling.setId(null);
            gpProcessScheduling.setSn(getSn());
            this.save(gpProcessScheduling);
        }
        return true;
    }


    /**
     * 获取生成加工订单号
     */
    private String getSn() {
        String sn = "";

        String yyMMdd = DateUtils.getDate("yyMMdd");
        sn += yyMMdd;

        GpProcessScheduling processScheduling = this.getOne(new LambdaQueryWrapper<GpProcessScheduling>()
                .eq(GpProcessScheduling::getDelStatus, YesNoEnum.NO.getKey())
                .isNotNull(GpProcessScheduling::getSn)
                .gt(GpProcessScheduling::getCreateTime, DateUtils.getDate("yyyy-MM-dd 00:00:00"))
                .orderByDesc(GpProcessScheduling::getCreateTime)
                .last("limit 1"));
        if (processScheduling == null) {
            sn += "-1";
        } else {
            String[] split = processScheduling.getSn().split("-");
            sn += "-" + (Integer.valueOf(split[1])+1);
            //processScheduling.getSn().substring(processScheduling.getSn().lastIndexOf("-"));
        }
        return sn;
    }


    /**
     * 获取生成加工订单号
     * @param
     */
    private String getSplitSn(String beforSn) {
        String sn = "";

        String yyMMdd = DateUtils.getDate("yyMMdd");
        sn += yyMMdd;

        GpProcessScheduling processScheduling = this.getOne(new LambdaQueryWrapper<GpProcessScheduling>()
                .eq(GpProcessScheduling::getDelStatus, YesNoEnum.NO.getKey())
                .isNotNull(GpProcessScheduling::getSn)
                .gt(GpProcessScheduling::getCreateTime, DateUtils.getDate("yyyy-MM-dd 00:00:00"))
                .orderByDesc(GpProcessScheduling::getCreateTime)
                .last("limit 1"));
        if (processScheduling == null) {
            sn += "-1";
        } else {
            sn += processScheduling.getSn().substring(processScheduling.getSn().lastIndexOf("-"));
        }
        return sn;
    }

}
